#include "./BSP/LCD/lcd_init.h"
#include "./BSP/LCD/lcd.h"

/* --------------------------------------------- 全局变量 ------------------------------------------------ */

static uint8_t g_lcd_direction = 0;     /* LCD显示方向 */

#if USE_PWM_BLK
static uint8_t g_lcd_brightness = 100;  /* LCD显示亮度 */

TIM_HandleTypeDef g_lcd_blk_tim_handler;        /* BLK定时器句柄 */
TIM_OC_InitTypeDef g_lcd_blk_tim_oc_handler;    /* BLK定时器通道句柄 */
#endif

/* -------------------------------------------- 显示控制函数 ---------------------------------------------- */

/**
 * @brief 设置LCD显示方向 - ST7796版本
 * @param direction 显示方向(0-3)
 *        0: 0度 (竖屏)
 *        1: 180度 (竖屏翻转)
 *        2: 90度 (横屏)
 *        3: 270度 (横屏翻转)
 * @return 无
 */
void LCD_SetDirection(uint8_t direction)
{
    if (direction > 3) 
    {
        return; /* 无效的方向值 */
    }
    
    g_lcd_direction = direction;
    
    /* 重新配置LCD - ST7796的MADCTL参数 */
    LCD_WR_REG(0x36);  /* MADCTL: Memory Data Access Control */
    
    switch (direction)
    {
        case 0:  /* 0度 (竖屏) */
            LCD_WR_DATA8(0x48);
            break;
        case 1:  /* 180度 (竖屏翻转) */
            LCD_WR_DATA8(0x88);
            break;
        case 2:  /* 90度 (横屏) */
            LCD_WR_DATA8(0x28);
            break;
        case 3:  /* 270度 (横屏翻转) */
            LCD_WR_DATA8(0xE8);
            break;
    }
    
    /* ST7796通常不需要重新设置显示区域，硬件自动处理 */
    /* 如果有问题，可以取消下面的注释 */
    /*
    switch (direction)
    {
        case 2:  // 90度
        case 3:  // 270度
            LCD_Address_Set(0, 0, LCD_H - 1, LCD_W - 1);
            break;
        default: // 0度和180度
            LCD_Address_Set(0, 0, LCD_W - 1, LCD_H - 1);
            break;
    }
    */
    
    /* 清除屏幕内容 */
    LCD_Clear();
}

/**
 * @brief 获取当前LCD显示方向
 * @return 当前显示方向(0-3)
 */
uint8_t LCD_GetDirection(void)
{
    return g_lcd_direction;
}


/* 设置LCD背光亮度(0-100) */
void LCD_SetBacklight(uint8_t brightness)
{
    if (brightness > 100)
    {
        brightness = 100;
    }
#if USE_PWM_BLK
    /* 更新全局亮度变量 */
    g_lcd_brightness = brightness;

    /* 计算PWM占空比值 */
    uint32_t pulse = (brightness * (g_lcd_blk_tim_handler.Init.Period + 1)) / 100;

    /* 更新PWM占空比 */
    __HAL_TIM_SET_COMPARE(&g_lcd_blk_tim_handler, LCD_BLK_TIMX_CHY, pulse);
#endif
}


#if USE_HARDWARE_SPI
/* -------------------------------------------- 硬件SPI配置 -------------------------------------------- */
void SPI2_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    /* 使能SPI2和GPIO时钟 */
    __HAL_RCC_SPI2_CLK_ENABLE();                            /* 使能SPI2时钟 */
    __HAL_RCC_GPIOB_CLK_ENABLE();                           /* 使能GPIOB时钟 */

    /* 配置SPI2引脚 */
    GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_15;          /* SCK: PB13, MOSI: PB15 */
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;                 /* 复用推挽输出 */
    GPIO_InitStruct.Pull = GPIO_NOPULL;                     /* 无上拉下拉 */
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;           /* 高速 */
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);                 /* 初始化GPIO */

    /* 配置SPI2参数 */
    hspi2.Instance = SPI2;                                  /* 选择SPI2 */
    hspi2.Init.Mode = SPI_MODE_MASTER;                      /* 主机模式 */
    hspi2.Init.Direction = SPI_DIRECTION_1LINE;             /* 单线发送模式 */
    hspi2.Init.DataSize = SPI_DATASIZE_8BIT;                /* 8位数据帧 */
    hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH;             /* 时钟空闲时为高电平 */
    hspi2.Init.CLKPhase = SPI_PHASE_2EDGE;                  /* 第二个时钟沿采样 */
    hspi2.Init.NSS = SPI_NSS_SOFT;                          /* 软件控制片选 */
    hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; /* 波特率分频因子2 */
    hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;                 /* 高位先行 */
    hspi2.Init.TIMode = SPI_TIMODE_DISABLE;                 /* 禁用TI模式 */
    hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; /* 禁用CRC */
    hspi2.Init.CRCPolynomial = 10;                          /* CRC多项式(未使用) */

    /* 初始化SPI2 */
    if (HAL_SPI_Init(&hspi2) != HAL_OK)                     /* 初始化配置 */
    {
        Error_Handler();
    }
}
#endif

/* -------------------------------------------- GPIO初始化 -------------------------------------------- */

/**
 * @brief LCD GPIO引脚初始化
 * @details 配置LCD所需的所有GPIO引脚，包括SCL、SDA、RES、DC、CS和BLK
 * @note 所有引脚配置为推挽输出，高速模式，无上拉下拉
 * @return 无
 */
void LCD_GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    /* 使能时钟 */
#if !USE_HARDWARE_SPI
    LCD_SCL_GPIO_CLK_ENABLE();                              /* LCD_SCL脚时钟使能 */
    LCD_SDA_GPIO_CLK_ENABLE();                              /* LCD_SDA脚时钟使能 */
#endif
    LCD_RES_GPIO_CLK_ENABLE();                              /* LCD_RES脚时钟使能 */
    LCD_DC_GPIO_CLK_ENABLE();                               /* LCD_DC脚时钟使能 */
#if USE_LCD_CS
    LCD_CS_GPIO_CLK_ENABLE();                               /* LCD_CS脚时钟使能 */
#endif
    LCD_BLK_GPIO_CLK_ENABLE();                              /* LCD_BLK脚时钟使能 */

    /* 配置引脚 */
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;             /* 推挽复用 */
    GPIO_InitStruct.Pull = GPIO_NOPULL;                     /* 无上拉下拉 */
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;           /* 高速 */
    
#if !USE_HARDWARE_SPI
    GPIO_InitStruct.Pin = LCD_SCL_GPIO_PIN;
    HAL_GPIO_Init(LCD_SCL_GPIO_PORT, &GPIO_InitStruct);     /* LCD_SCL引脚模式设置(推挽输出) */

    GPIO_InitStruct.Pin = LCD_SDA_GPIO_PIN;
    HAL_GPIO_Init(LCD_SDA_GPIO_PORT, &GPIO_InitStruct);     /* 初始化LCD_SDA引脚 */
#endif

    GPIO_InitStruct.Pin = LCD_RES_GPIO_PIN;
    HAL_GPIO_Init(LCD_RES_GPIO_PORT, &GPIO_InitStruct);     /* 初始化LCD_RES引脚 */

    GPIO_InitStruct.Pin = LCD_DC_GPIO_PIN;
    HAL_GPIO_Init(LCD_DC_GPIO_PORT, &GPIO_InitStruct);      /* 初始化LCD_DC引脚 */

#if USE_LCD_CS
    GPIO_InitStruct.Pin = LCD_CS_GPIO_PIN;
    HAL_GPIO_Init(LCD_CS_GPIO_PORT, &GPIO_InitStruct);      /* 初始化LCD_CS引脚 */
#endif

#if USE_PWM_BLK
    /* 先使能时钟 */
    LCD_BLK_TIMX_CLK_ENABLE();                              /* 使能BLK定时器时钟 */
    LCD_BLK_GPIO_CLK_ENABLE();                              /* 使能BLK GPIO时钟 */
    
    /* 配置BLK引脚为PWM输出模式 */
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;                 /* 复用推挽输出 */
    GPIO_InitStruct.Pin = LCD_BLK_GPIO_PIN;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = LCD_BLK_GPIO_AFTIMX;
    HAL_GPIO_Init(LCD_BLK_GPIO_PORT, &GPIO_InitStruct);     /* 初始化BLK引脚为PWM输出 */
    
    /* 然后初始化PWM定时器 */
    LCD_BLK_PWM_Init(1311, 79);                             /* 初始化BLK PWM定时器，频率0.8kHz */
#else
    /* 配置BLK引脚为普通GPIO输出模式 */
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;             /* 推挽输出 */
    GPIO_InitStruct.Pin = LCD_BLK_GPIO_PIN;
    HAL_GPIO_Init(LCD_BLK_GPIO_PORT, &GPIO_InitStruct);     /* 初始化LCD_BLK引脚为普通输出 */
#endif

    /* 设置引脚初始电平 */
#if !USE_HARDWARE_SPI
    LCD_SCL(1);                                             /* SCL 默认高电平 */
    LCD_SDA(1);                                             /* SDA 默认高电平 */
#endif
    LCD_RES(1);                                             /* RES 默认高电平 */
    LCD_DC(1);                                              /* DC 默认高电平 */
#if USE_LCD_CS
    LCD_CS(1);                                              /* CS 默认高电平 */
#endif
#if !USE_PWM_BLK
    LCD_BLK(1);                                             /* BLK默认高电平 */
#endif
}

/* -------------------------------------------- SPI通信函数 -------------------------------------------- */

/**
 * @brief LCD串行数据写入函数
 * @param dat 要写入的串行数据，范围0x00-0xFF
 * @details 通过模拟SPI方式，将8位数据写入LCD
 * @note 数据按位从高到低依次写入，每位写入时序：SCL低-设置SDA-SCL高
 * @return 无
 */
void LCD_Writ_Bus(uint8_t dat)
{
#if USE_HARDWARE_SPI
    /* 使用硬件SPI发送数据 */
#if USE_LCD_CS
    LCD_CS(0);  /* 使能片选，开始传输 */
#endif
    HAL_SPI_Transmit(&hspi2, &dat, 1, HAL_MAX_DELAY);
#if USE_LCD_CS
    LCD_CS(1);  /* 禁用片选，结束传输 */
#endif
#else
    /* 使用软件模拟SPI发送数据 */
    uint8_t i;
#if USE_LCD_CS
    LCD_CS(0);  /* 使能片选，开始传输 */
#endif
    for (i = 0; i < 8; i++)
    {
        LCD_SCL(0);
        if (dat & 0x80)
        {
            LCD_SDA(1);
        }
        else
        {
            LCD_SDA(0);
        }
        LCD_SCL(1);
        dat <<= 1;
    }
#if USE_LCD_CS
    LCD_CS(1);  /* 禁用片选，结束传输 */
#endif
#endif
}

/**
 * @brief LCD写入8位数据
 * @param dat 要写入的8位数据，范围0x00-0xFF
 * @details 直接调用LCD_Writ_Bus函数写入8位数据
 * @return 无
 */
void LCD_WR_DATA8(uint8_t dat)
{
    LCD_Writ_Bus(dat);
}

/**
 * @brief LCD写入16位数据
 * @param dat 要写入的16位数据，范围0x0000-0xFFFF
 * @details 将16位数据分两次写入，先写高8位，再写低8位
 * @return 无
 */
void LCD_WR_DATA(uint16_t dat)
{
    LCD_Writ_Bus(dat >> 8);
    LCD_Writ_Bus(dat);
}

/**
 * @brief LCD写入命令
 * @param dat 要写入的命令，范围0x00-0xFF
 * @details 写入命令时DC引脚置低，写入后恢复高电平
 * @return 无
 */
void LCD_WR_REG(uint8_t dat)
{
    LCD_DC(0); /* 写命令 */
    LCD_Writ_Bus(dat);
    LCD_DC(1); /* 写数据 */
}

/**
 * @brief 设置LCD显示区域
 * @param x1 列起始地址，范围0~LCD_W-1
 * @param y1 行起始地址，范围0~LCD_H-1
 * @param x2 列结束地址，范围0~LCD_W-1
 * @param y2 行结束地址，范围0~LCD_H-1
 * @details 设置LCD的显示窗口区域，用于后续的像素数据写入
 * @note ST7796驱动芯片会根据MADCTL设置自动处理坐标映射，无需软件调整
 * @return 无
 */
void LCD_Address_Set(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
{
    LCD_WR_REG(0x2a);  /* 列地址设置 */
    LCD_WR_DATA(x1);
    LCD_WR_DATA(x2);
    LCD_WR_REG(0x2b);  /* 行地址设置 */
    LCD_WR_DATA(y1);
    LCD_WR_DATA(y2);
    LCD_WR_REG(0x2c);  /* 储存器写 */
}

/* -------------------------------------------- LCD初始化 -------------------------------------------- */

/**
 * @brief LCD初始化函数
 * @details 完成LCD的GPIO初始化、复位序列和寄存器配置
 * @note 初始化顺序：GPIO初始化->硬件复位->开启背光->寄存器配置
 * @return 无
 */
void LCD_Init(void)
{
    LCD_GPIO_Init(); /* 初始化GPIO引脚，配置SPI、复位、背光等控制信号 */

#if USE_HARDWARE_SPI
    SPI2_Init();  /* 初始化硬件SPI */
#endif

    LCD_RES(0);     /* 拉低复位引脚，启动硬件复位 */
    HAL_Delay(100); /* 维持复位信号延时 */
    LCD_RES(1);     /* 释放复位引脚 */
    HAL_Delay(100); /* 等待复位完成 */
    
#if USE_PWM_BLK
    /* 设置初始背光亮度 */
    LCD_SetBacklight(g_lcd_brightness);
    HAL_Delay(100); /* 背光稳定延时 */
#endif
    
    /* ------------------------------------------- 初始化序列开始 ----------------------------------------------- */
    /* 命令 0x11: Sleep Out (退出睡眠模式) */
    LCD_WR_REG(0x11); /* SLPOUT命令，退出睡眠模式 */
    HAL_Delay(120);   /* 退出睡眠后等待时间 */

    /* 设置初始显示方向 */
    LCD_SetDirection(g_lcd_direction);

    /* 命令 0x3A: COLMOD (接口像素格式) */
    LCD_WR_REG(0x3A);   /* COLMOD，设置颜色模式 */
    LCD_WR_DATA8(0x05); /* 0x05 = RGB565 (16位/像素) */

    /* ------------------------------------------------ 显示控制设置 ------------------------------------------------ */
    /* 命令 0xB6: DISCTRL (显示功能控制) */
    LCD_WR_REG(0xB6);   /* DISCTRL，显示功能控制 */
    LCD_WR_DATA8(0x0A); /* PT[1:0]: 部分显示模式设置 */
    LCD_WR_DATA8(0x82); /* PTG[1:0]: 部分显示间隔，REV: 扫描方向 */
    LCD_WR_DATA8(0x27); /* ISC[3:0]: 扫描周期设置 */
    LCD_WR_DATA8(0x00); /* SM: 源输出模式设置 */

    /* 命令 0xB7: ETMOD (入口模式设置) */
    LCD_WR_REG(0xB7);   /* ETMOD，入口模式设置 */
    LCD_WR_DATA8(0xC6); /* 低功耗模式控制参数 */

    /* ------------------------------------------------ 电源控制设置 ------------------------------------------------ */
    /* 命令 0xC0: PWCTR1 (电源控制1) */
    LCD_WR_REG(0xC0);   /* PWCTR1，电源控制1 */
    LCD_WR_DATA8(0x17); /* VRH[5:0]: GVDD电压控制 */
    LCD_WR_DATA8(0x15); /* VC[2:0]: VCI1电压控制 */

    /* 命令 0xC1: PWCTR2 (电源控制2) */
    LCD_WR_REG(0xC1);   /* PWCTR2，电源控制2 */
    LCD_WR_DATA8(0x41); /* BT[2:0]: 升压电路控制 */

    /* 命令 0xC5: VMCTR1 (VCOM控制1) */
    LCD_WR_REG(0xC5);   /* VMCTR1，VCOM控制1 */
    LCD_WR_DATA8(0x00); /* VMH[6:0]: VCOMH电压设置 */
    LCD_WR_DATA8(0x12); /* VML[6:0]: VCOML电压设置 */
    LCD_WR_DATA8(0x80); /* nVM: VCOM使能控制 */

    /* ------------------------------------------------ 帧率控制设置 ------------------------------------------------ */
    /* 命令 0xB1: FRMCTR1 (正常模式帧率控制) */
    LCD_WR_REG(0xB1);   /* FRMCTR1，正常模式帧率控制 */
    LCD_WR_DATA8(0x80); /* RTNA[4:0]: 正常模式帧率设置 */
    LCD_WR_DATA8(0x10); /* FPA[5:0]: 前肩时间设置 */
    LCD_WR_DATA8(0x14); /* BPA[5:0]: 后肩时间设置 */

    /* 命令 0xB2: FRMCTR2 (空闲模式帧率控制) */
    LCD_WR_REG(0xB2);   /* FRMCTR2，空闲模式帧率控制 */
    LCD_WR_DATA8(0x80); /* RTNA[4:0]: 空闲模式帧率设置 */
    LCD_WR_DATA8(0x10); /* FPA[5:0]: 前肩时间设置 */
    LCD_WR_DATA8(0x14); /* BPA[5:0]: 后肩时间设置 */

    /* ------------------------------------------------ 接口控制设置 ------------------------------------------------ */
    /* 命令 0xF6: IFCTL (接口控制) */
    LCD_WR_REG(0xF6);   /* 接口控制 */
    LCD_WR_DATA8(0x01); /* MY_EOR: 0, MX_EOR: 0, MV_EOR: 0, BGR_EOR: 1 */
    LCD_WR_DATA8(0x00); /* 接口模式控制 */
    LCD_WR_DATA8(0x00); /* 保留位 */

    /* ------------------------------------------------ 伽马校正设置 ------------------------------------------------ */
    /* 命令 0xE0: PVGAMCTRL (正电压伽马校正) */
    LCD_WR_REG(0xE0);   /* PVGAMCTRL，正伽马校正（14个参数） */
    LCD_WR_DATA8(0xF0); /* VP0：最高灰度级电压调整 */
    LCD_WR_DATA8(0x01); /* VP1：高灰度区域1电压调整 */
    LCD_WR_DATA8(0x06); /* VP2：高灰度区域2电压调整 */
    LCD_WR_DATA8(0x0F); /* VP3：高灰度区域3电压调整 */
    LCD_WR_DATA8(0x12); /* VP4：中高灰度区域1电压调整 */
    LCD_WR_DATA8(0x1D); /* VP5：中高灰度区域2电压调整 */
    LCD_WR_DATA8(0x36); /* VP6：中灰度区域1电压调整 */
    LCD_WR_DATA8(0x54); /* VP7：中灰度区域2电压调整 */
    LCD_WR_DATA8(0x44); /* VP8：中灰度区域3电压调整 */
    LCD_WR_DATA8(0x0C); /* VP9：中低灰度区域1电压调整 */
    LCD_WR_DATA8(0x18); /* VP10：中低灰度区域2电压调整 */
    LCD_WR_DATA8(0x16); /* VP11：低灰度区域1电压调整 */
    LCD_WR_DATA8(0x13); /* VP12：低灰度区域2电压调整 */
    LCD_WR_DATA8(0x15); /* VP13：最低灰度级电压调整 */

    /* 命令 0xE1: NVGAMCTRL (负电压伽马校正) */
    LCD_WR_REG(0xE1);   /* NVGAMCTRL，负伽马校正（14个参数） */
    LCD_WR_DATA8(0xF0); /* VN0：负极性最高灰度级电压调整 */
    LCD_WR_DATA8(0x01); /* VN1：负极性高灰度区域1电压调整 */
    LCD_WR_DATA8(0x05); /* VN2：负极性高灰度区域2电压调整 */
    LCD_WR_DATA8(0x0A); /* VN3：负极性高灰度区域3电压调整 */
    LCD_WR_DATA8(0x0B); /* VN4：负极性中高灰度区域1电压调整 */
    LCD_WR_DATA8(0x07); /* VN5：负极性中高灰度区域2电压调整 */
    LCD_WR_DATA8(0x32); /* VN6：负极性中灰度区域1电压调整 */
    LCD_WR_DATA8(0x44); /* VN7：负极性中灰度区域2电压调整 */
    LCD_WR_DATA8(0x44); /* VN8：负极性中灰度区域3电压调整 */
    LCD_WR_DATA8(0x0C); /* VN9：负极性中低灰度区域1电压调整 */
    LCD_WR_DATA8(0x18); /* VN10：负极性中低灰度区域2电压调整 */
    LCD_WR_DATA8(0x17); /* VN11：负极性低灰度区域1电压调整 */
    LCD_WR_DATA8(0x13); /* VN12：负极性低灰度区域2电压调整 */
    LCD_WR_DATA8(0x16); /* VN13：负极性最低灰度级电压调整 */

    /* 命令 0x20: INVOFF (显示反转关闭) */
    LCD_WR_REG(0x20); /* INVOFF: 关闭显示反转 */

    /* 在显示开启前清屏，解决花屏问题 */
    LCD_Fill(0, 0, LCD_W, LCD_H, g_back_color);
    
    /* 命令 0x29: DISPON (显示开启) */
    LCD_WR_REG(0x29); /* DISPON，使能显示输出 */
}

#if USE_PWM_BLK
/**
 * @brief      BLK PWM定时器初始化函数
 * @param[in]  arr         自动重装载值,决定PWM频率
 * @param[in]  psc         时钟预分频数,决定定时器计数频率
 *
 * @note       定时器的时钟来自APB1 / APB2, 当APB1 / APB2 分频时, 定时器频率自动翻倍
 *             定时器溢出时间计算方法: Tout = ((arr + 1) * (psc + 1)) / Ft us.
 *             Ft = 定时器工作频率, 单位: Mhz
 * @retval     无
 */
void LCD_BLK_PWM_Init(uint16_t arr, uint16_t psc)
{
    /* 配置定时器基本参数 */
    g_lcd_blk_tim_handler.Instance = LCD_BLK_TIMX;                  /* BLK定时器 */
    g_lcd_blk_tim_handler.Init.Prescaler = psc;                     /* 设置预分频器 */
    g_lcd_blk_tim_handler.Init.CounterMode = TIM_COUNTERMODE_UP;    /* 向上计数模式 */
    g_lcd_blk_tim_handler.Init.Period = arr;                        /* 自动重装载值 */
    HAL_TIM_PWM_Init(&g_lcd_blk_tim_handler);                       /* 初始化PWM定时器 */

    /* 配置PWM通道参数 */
    g_lcd_blk_tim_oc_handler.OCMode = TIM_OCMODE_PWM1;              /* PWM模式1: CNT<CCR时输出有效电平 */
    g_lcd_blk_tim_oc_handler.Pulse = arr;                           /* 设置比较值为arr，初始占空比为100% */
    g_lcd_blk_tim_oc_handler.OCPolarity = TIM_OCPOLARITY_HIGH;      /* 输出极性为高电平有效 */
    HAL_TIM_PWM_ConfigChannel(&g_lcd_blk_tim_handler, &g_lcd_blk_tim_oc_handler, LCD_BLK_TIMX_CHY); /* 配置BLK定时器通道 */

    /* 启动PWM输出 */
    HAL_TIM_PWM_Start(&g_lcd_blk_tim_handler, LCD_BLK_TIMX_CHY);
}

/**
 * @brief      定时器PWM底层初始化回调函数
 * @param[in]  htim        定时器句柄指针
 *
 * @note       该函数会被HAL_TIM_PWM_Init()自动调用
 * @retval     无
 */
//void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
//{
//    GPIO_InitTypeDef gpio_init_struct;

//    if (htim->Instance == LCD_BLK_TIMX)
//    {
//        LCD_BLK_TIMX_CLK_ENABLE();           /* 使能BLK引脚定时器时钟 */
//        
//        /* 初始化BLK PWM引脚 */
//        LCD_BLK_GPIO_CLK_ENABLE();
//        gpio_init_struct.Pin = LCD_BLK_GPIO_PIN;
//        gpio_init_struct.Mode = GPIO_MODE_AF_PP;
//        gpio_init_struct.Pull = GPIO_PULLUP;
//        gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;
//        gpio_init_struct.Alternate = LCD_BLK_GPIO_AFTIMX;
//        HAL_GPIO_Init(LCD_BLK_GPIO_PORT, &gpio_init_struct);
//    }
//}
#endif
